﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using WebSiteAdminTool.Web.Services.DTOs;
using System.Web.Security;
using WebSiteAdminTool.Web.Services.Contracts;
using WebSiteAdminTool.Web.Services.Base;
using WebSiteAdminTool.Web.Services.Utils;

namespace WebSiteAdminTool.Web.Services
{
    public class MembershipService : BaseService, IMembershipService
    {
        public UserData[] GetUsers(Constants.UserSearchCriteria searchBy, string value)
        {
            IEnumerable<MembershipUser> users = null;
            // TODO fix and test wildcards
            value = value.Replace("*", "%");
            value = value.Replace("?", "%");
            switch (searchBy)
            {
                case Constants.UserSearchCriteria.None:
                    users = Membership.GetAllUsers().Cast<MembershipUser>();
                    break;
                case Constants.UserSearchCriteria.UserName:
                    if (string.IsNullOrWhiteSpace(value))
                        users = new MembershipUser[] { };
                    else
                        users = Membership.FindUsersByName(value).Cast<MembershipUser>();
                    break;
                case Constants.UserSearchCriteria.Email:
                    if (string.IsNullOrWhiteSpace(value))
                        users = new MembershipUser[] { };
                    else
                        users = Membership.FindUsersByEmail(value).Cast<MembershipUser>();
                    break;
                case Constants.UserSearchCriteria.IsOnline:
                    users = Membership.GetAllUsers().Cast<MembershipUser>()
                        .Where(u => u.IsOnline)
                        .ToArray();
                    break;
                case Constants.UserSearchCriteria.RoleName:
                    throw new NotImplementedException();
            }

            return MembersToUserDTOs(users);
        }

        public int GetNumberOfUsersOnline()
        {
            return Membership.GetNumberOfUsersOnline();
        }

        public bool ValidateUser(string userName, string password)
        {
            return Membership.ValidateUser(userName, password);
        }

        public string GenerateValidPassword()
        {
            return Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters);
        }

        public string ResetPassword(object userId)
        {
            if (Membership.EnablePasswordReset)
            {
                MembershipUser user = Membership.GetUser(userId);
                if (null != user)
                {
                    return user.ResetPassword();
                }

            }
            return null;
        }

        public UserPasswordConstraintsData GetPasswordConstraints()
        {
            return new UserPasswordConstraintsData
                {
                    EnablePasswordReset = Membership.EnablePasswordReset,
                    EnablePasswordRetrieval = Membership.EnablePasswordRetrieval,
                    MaxInvalidPasswordAttempts = Membership.MaxInvalidPasswordAttempts,
                    MinRequiredNonAlphanumericCharacters = Membership.MinRequiredNonAlphanumericCharacters,
                    MinRequiredPasswordLength = Membership.MinRequiredPasswordLength,
                    PasswordAttemptWindow = Membership.PasswordAttemptWindow,
                    PasswordStrengthRegularExpression = Membership.PasswordStrengthRegularExpression,
                    RequiresQuestionAndAnswer = Membership.RequiresQuestionAndAnswer
                };
        }

        public UserData CreateUser(UserData user, string password, string passwordAnswer)
        {
            MembershipCreateStatus status;
            if (null != user && user.Validate())
            {
                var member = Membership.CreateUser(user.UserName, password, user.Email,
                    user.PasswordQuestion, passwordAnswer, user.IsApproved,
                    user.Id, out status);

                if (status != MembershipCreateStatus.Success)
                    throw new Exception(status.ToString());

                // TODO: update other user attributes
                return new UserData(member);
            }
            return null;
        }

        public UserData UpdateUser(UserData user)
        {
            if (null != user && user.Validate())
            {
                // its not possible to update role name due to role name usage
                // TODO: update other role attributes
            }

            return user;
        }

        public bool RemoveUser(string userName, bool deleteAllRelatedData = false)
        {
            return Membership.DeleteUser(userName, deleteAllRelatedData);
        }

        #region helpers

        private UserData[] MembersToUserDTOs(IEnumerable<MembershipUser> users)
        {
            return users
                .Select(u =>
                {
                    return new UserData(u, GetUserRoles(u.UserName));
                }).ToArray();
        }

        private string[] GetUserRoles(string userName)
        {
            string[] userRoles = IsRoleManagementEnabled ? Roles.GetRolesForUser(userName) : null;
            return userRoles;
        }

        #endregion
    }
}
